/* mv_seq.c

   Sequential implementation of the matrix-vector multiplication.
   Limitation: impose double operation to all values

   Usge:
   	mv_seq <matrix> <vector>

   Second version. The first version (bigger, with run-time appreciation of integer or double, ...) was accidentally deleted by myself ...
   For the format of the matrix and vector files, see the README file in this directory.
   Basile Clout, September 2007

   */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mv.h"

#define FILENAME "/tmp/tmp.res"

int main(int argc, char *argv[]){

  int m=0, n=0;
  int i,j;
  int mv=0, nv=0;
  int typev=0, lv=0;	/* Values for the vector. lv is the length of the vector */
  FILE *vecS;
  FILE *matS;
  FILE *resS;
  double **mat;
  double *vec;
  double *res;
  int nb=0;
  int type=0;			/* If type=0, integer, else, double. Not really important now. Just send a warning in case of at least one of the matrix or vector contains integers */
  int dummy;			/* Dummy int, here contains the max range, we don't care here */

  struct timeval t0, t1, t2;

  double ttotal, tio, tcomp;
  
  CLOCK(t0);
  
  if (argc!=3){
    printf("Usage: %s <matrix> <vector>\n", argv[0]);
    exit(1);
  }

  /* Open files */
  if(!(matS = fopen(argv[1], "r"))){
    printf("Error: Impossible to open given matrix file.\n");
    exit(1);
  }
  if(!(vecS = fopen(argv[2], "r"))){
    printf("Error: Impossible to open given vector file.\n");
    exit(1);
  }

  /* Get infos from matrix file */
  nb = fscanf(matS, "%d", &m);
  nb += fscanf(matS, "%d", &n);
  nb += fscanf(matS, "%d", &dummy);
  nb += fscanf(matS, "%d", &type);

  if(nb!=4){
    printf("Error when parsing first line of the matrix file (%d int parsed).\n", nb);
    exit(1);
  }

  /* Get infos from vector file */
  nb = fscanf(vecS, "%d", &mv);
  nb += fscanf(vecS, "%d", &nv);
  nb += fscanf(vecS, "%d", &dummy);
  nb += fscanf(vecS, "%d", &typev);

  if(nb!=4){
    printf("Error when parsing first line of the vector file.\n");
    exit(1);
  }

  
  /* Check conformity matrix/vector */
  if(mv != 1 && nv != 1){
    printf("Error: the vector is not a vector (mv=%d, nv=%d)!!\n", mv, nv);
    exit(1);
  }
  
  lv = (mv==1) ? nv : mv;
  if (lv != n){
    printf("Error: please enter the matrix in a way that length(vector) = numberofcolumns(matrix).\n");
    exit(1);
  }

  if(WARNING){
    if (type==0)
      printf("Warning!: integer multiplication is no more implemented (lost everything, ouiiinnnn!). The program is going to cast everything to double!\n");
    if(type!=typev)
      printf("Warning!: matrix and vector values are of different types. Everything is going to be cast to double!\n");
  }
  
  /* Malloc matrix */

  mat = (double **) malloc(m*sizeof(double *));
  if(!mat){
    printf("Impossible to malloc memory for matrix.\n");
    exit(1);
  }
  for (i=0;i<m;i++){
    mat[i] = (double *) malloc(n*sizeof(double));
    if(!mat[i]){
      printf("Impossible to malloc memory for the matrix.\n");
      exit(1);
    }
  }
  
  /* And fill it */
  for (i=0;i<m;i++){
    for(j=0;j<n;j++){
      nb = fscanf(matS, "%lf", &mat[i][j]);
      if (nb!=1){
	printf("Error when filling matrix.\n");
	exit(1);
      }
    }
  }


    /* Malloc vector */
  vec = (double *) malloc(n*sizeof(double));
  if (!vec){
    printf("Impossible to malloc memory for matrix.\n");
    exit(1);
  }

  /* And fill it */
  for(i=0;i<n;i++){
    nb = fscanf(vecS, "%lf", &vec[i]);
    if (nb!=1){
      printf("Error when filling vector memory structure.\n");
      exit(1);
    }
  }

  /* Malloc result vector */
  res = (double *) malloc (m*sizeof(double));
  if (!res){
    printf("Error: Impossible to malloc result vector.\n");
    exit(1);
  }

  CLOCK(t1);
  /* Multiplication proper */
  if(!mvd((const double **)mat, (const double *) vec, res, m, n)){
    printf("Error in the multiplication proper!\n");
    exit(1);
  }
  CLOCK(t2);

  if (PRINT){
    printf("Result:\n");
    for (i=0;i<m;i++)
      printf("%.2f ", res[i]);
  }
  printf("\n");

  if (PRINT_FILE) {
    if(!(resS = fopen(FILENAME, "w"))){
      printf("ERROR: Impossible to create the file %s\n", FILENAME);
      exit(1);
    }
    fprintf(resS, "%d\n", m);
    for (i=0; i<m;i++)
      fprintf(resS, "%.2f ", res[i]);
	fclose(resS);
  }

  if (TIME){

    ttotal = CLOCK_DIFF(t2, t0);
    tio = CLOCK_DIFF(t1, t0);
    tcomp = CLOCK_DIFF(t2, t1);
    printf("Total time (s): %.6f\n", ttotal);
    printf("\tIO time: %.6f\n", tio);
    printf("\tComputation time: %.6fs.\n", tcomp);

    printf("\nStatistics: \n");
    printf("\tratio IO/total: %.2f%%\n", tio/ttotal*100.0);
    printf("\tratio comp/total: %.2f%%\n\n", tcomp/ttotal*100.0);
  }
  
  
  free(mat);
  free(vec);
  free(res);
  fclose(matS);
  fclose(vecS);

  exit(0);			/* Exit successfully!! */
}
